home *** CD-ROM | disk | FTP | other *** search
/ 2,000 Greater & Lesser Mysteries / 2,000 Greater and Lesser Mysteries.iso / internet / mys01119.txt < prev    next >
Encoding:
Text File  |  1994-06-10  |  16.0 KB  |  524 lines

  1. >From stinglai@bureau.World.GOV Tue Jun  5 08:50:55 1990
  2. From: stinglai@bureau.World.GOV (Stinglai Ka'abi)
  3. Newsgroups: alt.mud
  4. Subject: Beginner's guide to MUF programming
  5. Keywords: MUD Muck MUF forth Atlantis and a partridge in a pear tree
  6. Date: 5 Jun 90 09:19:45 GMT
  7. Reply-To: blojo@ocf.berkeley.edu
  8. Distribution: alt
  9.  
  10.  
  11. [ Updated August 10th, 1990, by ChupChup for the release of TinyMUCK 2.2. ]
  12.  
  13.                      Zen in the Art of the Towers of Hanoi
  14.                    (or The Basics of MUF in 10 megs or less.)
  15.  
  16.  
  17. This is an introduction to MUF, a dialect/subset of forth used to do really
  18. really neat things with TinyMuck 2.2.  This intro was designed to be read
  19. before any of the other MUF information; it (hopefully) should supply you
  20. with a fair idea of what MUF is all about.  It's written at a non-programming-
  21. stud level, all the better for understanding.
  22.  
  23.  
  24. All MUF programs work by performing operations on a stack.
  25.  
  26. For all you non-programmer types, a stack is just a tool used to store
  27. information.  Information is manipulated by "pushing" things onto the
  28. stack and "popping" things off.  The last thing you've placed on a stack
  29. is always the next thing you would take off if you tried; it's like
  30. piling objects on top of each other, when the only thing you can remove
  31. >from the pile is the thing on top.  For example, if you were to push the
  32. number 23, then push the number 42, and then pop a value off the stack,
  33. you would get 42.  If you were to pop another value off the stack after this,
  34. you would get 23.  If you were to try and pop another value, you would get
  35. an error, since the stack would now be empty.  (This is a "stack underflow.")
  36.  
  37. The basic procedural unit in MUF is called the word.  A word is simply a
  38. sequence of instructions.  In program text, a word always starts with a
  39. colon, then the word's name.  A semicolon marks the end of a word.
  40. For example:
  41.  
  42. : detonate_explosives
  43.         (text of word here)
  44. ;
  45.  
  46. would define a word called detonate_explosives.
  47.  
  48. Parentheses are used to delineate program comments; everything inside comments
  49. is ignored by the computer.  The detonate_explosives word above, if run
  50. as shown, would do absolutely nothing.
  51.  
  52. Indentation in MUF is arbitrary and serves to make the program more readable
  53. to people.
  54.  
  55.  
  56. In MUF, there are three types of constant values:  integers, strings, and
  57. database references.  Each of these types is stored and retrieved from the
  58. stack as a single unit (The string "Hello, Sailor!", for example, would be
  59. stored on the stack in its entirety: "Hello, Sailor!";  it would not be stored
  60. byte-by-byte or word-by-word or in any other such silly way.)
  61. To push a constant onto the stack, you only need to state its value.  The
  62. following is a completely legitimate procedure:
  63.  
  64. : pointless_word
  65.         "Old Man"
  66.         "I'm"
  67.         37
  68.         "What?"
  69.         37
  70.         "Not old!"
  71. ;
  72.  
  73. However, run by itself, it wouldn't do anything visible to the user.  It would,
  74. however, create a stack which looks like this:
  75.  
  76. ("Old Man"  "I'm"  37  "What?"  37  "Not old!")
  77.  
  78. In the above stack, "Old Man" is the value on the bottom.  "Not old!" is the
  79. value on top of the stack, and would be the next value retrieved.
  80.  
  81. Placement of values on the same line of a program is arbitrary.  Since each
  82. value represents something being put on a stack, the word
  83.  
  84. : example
  85.         "Semprini?"
  86.         "All right, wot's all this then!"
  87. ;
  88.  
  89. is the same as:
  90.  
  91. :example
  92.         "Semprini?" "All right, wot's all this then!"
  93. ;
  94.  
  95.  
  96. Functions which are available in the standard MUF library take values from the
  97. top of the stack, do things with them, and usually leave something new back
  98. on top of the stack.  The words +, -, swap, pop, and random provide good
  99. examples of this and are discussed here.
  100.  
  101. The + routine takes the top two integers from the stack, adds them together,
  102. and leaves the result on top of the stack.  In order to easily describe
  103. what functions like this do, a certain stack notation is used:  for +,
  104. this would be (i1 i2 -- z).  What's inside those parenthesis is a sort of
  105. "Before and After" synopsis; the things to the left of the double-dash are
  106. the "before", and those to the right are the "after".  (i1 i2 -- i) says that
  107. the function in question takes two integers away and leaves one.  The letters
  108. used here to tell what kind of data a stack object can be are:  i for integer,
  109. d for database object, s for string, v for variable, and x or y to mean
  110. something that can be more than one type.
  111.  
  112. Here are short descriptions of the procedures listed above so you can get
  113. the hang of how they work:
  114.  
  115.  
  116. + (i1 i2 -- i)
  117. Adds i1 and i2 together.  The word
  118.  
  119. : add_some_stuff
  120.         2 3 +
  121. ;
  122.  
  123. will return 5.  The word
  124.  
  125. : add_some_more_stuff
  126.         2 3 4
  127.         5
  128.         + + +
  129. ;
  130.  
  131. will return 14.  When add_some_more_stuff first reaches the "+ + +" line,
  132. the stack looks like:
  133.  
  134. (2 3 4 5).
  135.  
  136. The first + changes the stack to look like:
  137.  
  138. (2 3 9).
  139.  
  140. The next causes:
  141.  
  142. (2 12).
  143.  
  144. The final plus returns:
  145.  
  146. (14).
  147.  
  148.  
  149. - (i1 i2 -- i)
  150. Subtracts i2 from i1.
  151.  
  152. : subtract_arbitrary_things
  153.         10 7 -
  154. ;
  155.  
  156. will return 3 on top of the stack.
  157.  
  158.  
  159. swap (x y -- y x)
  160. Switches the top two things on the stack.  This is useful for when you want
  161. to know the value of x but want to save y for later use.
  162.  
  163. : swap_stuff_around
  164.         1 5
  165.         2 swap
  166.         3
  167.         "Three, sir!"
  168.         swap
  169.         "Boom!"
  170. ;
  171.  
  172. will, before it gets to the first swap, create a stack of (1 5 2).
  173. After the swap, the stack looks like (1 2 5).  It then accumulates another
  174. 3 and a string constant, to look like (1 2 5 3 "Three, sir!")  It swaps
  175. the last two again and adds another string, so the stack looks like:
  176. (1  2  5  "Three, sir!"  3  "Boom!").
  177.  
  178.  
  179. pop (x --)
  180. Throws away the value on top of the stack.  As shown in the stack diagram, it
  181. returns nothing but takes something, and so decreases the stack's total size.
  182. Useful when you really really want to get to the next thing on the stack so bad
  183. you don't care what's on top.  The word:
  184.  
  185. : needless_popping_waste
  186.         "Immanuel Kant"
  187.         "Heideggar"
  188.         pop
  189.         "David Hume"
  190.         "Schoppenhauer"
  191.         "Hegel"
  192.         pop pop
  193. ;
  194.  
  195. would leave the stack looking like ("Immanuel Kant"  "David Hume").
  196.  
  197.  
  198. random (-- i)
  199. Doesn't even look at the stack, but piles a really really random integer on
  200. top.  The word:
  201.  
  202. : feel_lucky_punkP
  203.         random
  204.         random
  205.         random
  206. ;
  207.  
  208. would return a stack of three random numbers.
  209.  
  210.  
  211. Because of the way the stack works, variables aren't as necessary in MUF as
  212. they are in other languages, but they can be used to simplify stack-handling
  213. operations.  To declare a variable, you simply add the line "var <name>"
  214. at the beginning of your program.  Variables are of no specific type; a
  215. variable which holds an integer can turn around the next second and hold
  216. a string if it's feeling haughty enough.
  217.  
  218. The following words are important when dealing with variables:
  219.  
  220. ! (x v --)
  221. Set variable v to hold value x.  The program:
  222.  
  223.  
  224. var answer
  225.  
  226. : multiply-and-store
  227.         6 9 *
  228.         answer
  229.         !
  230. ;
  231.  
  232. will give the variable "answer" the value 42.  This is the same as:
  233.  
  234. : multiply-and-store
  235.         6 9 * answer !
  236. ;
  237.  
  238.  
  239. @ (v -- x)
  240. This word (pronounced "fetch") retrieves the value of a variable and puts it
  241. on the stack.  You should remember this since a common mistake among beginning
  242. MUF programmers is to forget to put fetch symbols in their programs.
  243. The word
  244.  
  245.  garply
  246.  
  247. by itself stands for the variable "garply", while the expression
  248.  
  249.  garply @
  250.  
  251. stands for the value of that same variable.  If you're familiar with Lisp, this
  252. is analogous to the difference between garply and (garply).
  253.  
  254. The program:
  255.  
  256. var biggles
  257. var fang
  258. : more_silly_manipulation
  259.         10 biggles !
  260.         24 fang !
  261.         biggles @ fang @
  262.         +
  263. ;
  264.  
  265. will return the value 34 on top of the stack.  The program:
  266.  
  267. var biggles
  268. var fang
  269. : more_silly_manipulation
  270.         10 biggles !
  271.         24 fang !
  272.         biggles fang +
  273. ;
  274.  
  275. is *wrong*.  For reasons I won't go into now, since this guide was written
  276. at the last moment and at great expense, the above word will return the
  277. value 7 on top of the stack.
  278.  
  279.  
  280. In MUF, there are two variables which are predefined and available for use at
  281. all times.  These variables are "me" and "loc", where "me" holds the
  282. player's database reference, and loc holds the player's location's database
  283. reference.
  284.  
  285. (Database references were mentioned before as the third type of constant, then
  286. sort of ignored till now.  For the sake of completeness, I will introduce the
  287. word
  288.  
  289. dbref (i -- d)
  290. Where i is an integer and d is a database reference, dbref converts between
  291. the two types.  The line
  292.  
  293. 2032 dbref
  294.  
  295. will return item #2032 in the Muck database.  This is useful since there
  296. are lots of functions that operate on database references that won't work
  297. on integers.  [If you want to declare something in one of your programs as
  298. being a dbref instead of an integer, you should just put a # in front.  For
  299. example, 69 means the integer 69, while #69 means object number 69.  You
  300. could say '69 dbref' instead of '#69', but it would be a little slower and
  301. a little harder to read.]
  302.  
  303. Me @ will return the player's item reference, while loc @ will return the
  304. room they are in.  Trigger @ returns the item that triggered the current
  305. program, whether it is a player, exit, room, whatever.  A useful word to
  306. know is:
  307.  
  308. name (d -- s)
  309. Where d is a db reference and s is a string, name returns the name of item
  310. x.
  311.  
  312.  
  313. Now that you know about me @, another Muck function becomes useful.  Its
  314. synopsis is:
  315.  
  316. notify (d s --)
  317. When d is a player, notify prints string s out to user d.  The program
  318.  
  319. : warn
  320.         me @
  321.         "There is someone behind the next column waiting to jump you."
  322.         notify
  323. ;
  324.  
  325. would print said message on the user's screen.
  326.  
  327.  
  328. Before you can really start writing neat stuff in Muck, there are two more
  329. things you should know about.  One is = and the other is the "if/then" setup.
  330.  
  331. = (i1 i2 -- i)
  332. Returns 1 if integer i1 is equal to integer i2, otherwise returns 0.
  333.  
  334. : nonequals
  335.         2 3 =
  336. ;
  337.  
  338. returns 0.
  339.  
  340. If/then could be written up with a synopsis, but it would be sort of
  341. complicated and probably a lie also.  The way it works is this:  If
  342. pulls an item off the stack.  If the item is 0, it skips over the
  343. program after the IF and resumes execution at the THEN.  If the item is not
  344. 0, the program will execute everything in between.
  345.  
  346. The naming of this construction as if/then can be somewhat confusing.  It
  347. certainly doesn't work quite like the if/then of normal languages, and the
  348. THEN actually being called THEN is sort of confusing.  As nearly as I can
  349. tell, if/then is a sort of forth-creators' joke.  It does not mean
  350. "IF the previous is true THEN do this." like it does in most languages.
  351. Rather, it means "IF the previous is true do this; THEN go on with the rest
  352. of the program."  Remarkably silly.
  353. The word:
  354.  
  355. : word
  356.         2 3 =
  357.         if me @ "Your computer is broken!" notify
  358.         then me @ "Done executing this word." notify
  359. ;
  360.  
  361. will always print "Done executing this word." to the user, and will print
  362. "Your computer is broken!" if something is really screwy with the math and
  363. it actually thinks 2 = 3.  Getting a bit more sophisticated, one can write
  364. something like:
  365.  
  366. : word_up
  367.         "Your computer works fine."
  368.         2 3 =
  369.         if pop
  370.            "Your computer is broken. Sorry. Truth hurts."
  371.         then
  372.         me @ swap notify
  373. ;
  374. When word_up is called, "Your computer works fine." gets put on the stack.
  375. If your computer actually works, 2 is *not* equal to 3, so that right after
  376. the = the stack looks like:
  377.  
  378. ("Your computer works fine."  0)
  379.  
  380. The IF reads the 0 and skips all the way down to the THEN.
  381. The SWAP in the last line is used since the NOTIFY word wants its
  382. parameters in the opposite order of where they would be.
  383.  
  384. If your computer is broken, right after the =, the stack looks like:
  385.  
  386. ("Your computer works fine." 1)
  387.  
  388. The IF reads this 1 and decides to keep executing.  It then gets to the POP
  389. which gets rid of the filthy lie about well-working computers and replaces
  390. it with the painful truth.
  391.  
  392.  
  393. *SAMPLE PROGRAM*
  394.  
  395. Ok, so you've been reading this whole thing so far, and you really want to
  396. use this stuff to do something interesting.  The following program does
  397. something interesting, and uses the function
  398.  
  399. strcat (s1 s2 -- s)
  400. Concatenate strings s1 and s2, returning the result.
  401.  
  402. it also uses
  403.  
  404. location (d -- d')
  405. Takes db reference d and returns d', the db reference for its location.
  406.  
  407. and
  408.  
  409. dup (x -- x x)
  410. Duplicate the top of the stack.
  411.  
  412. and
  413.  
  414. dbcmp (d1 d2 -- )
  415. Works just like =, except operates on db references instead of integers.
  416.  
  417.  
  418. : far_vision
  419.         #2032        (2032 is Celia's object number.               )
  420.         dup           (Make 2 copies; we're about to use 1.         )
  421.         name          (Celia might change her name in the future, so)
  422.                       (instead of using "Celia" here we just look up)
  423.                       (her name.                                    )
  424.  
  425.         " is currently in "
  426.         strcat                (Attach name to sentence so far         )
  427.         swap                  (Flip the sentence back so we can get at)
  428.                               (Celia's dbref again.                   )
  429.  
  430.                       (Celia's dbref is now at top of stack.   )
  431.  
  432.         location      (Where is Celia?                         )
  433.         name          (What is the name of the place she is in?)
  434.         "." strcat strcat
  435.  
  436.         me @ swap notify    (Tell the player where Celia is.)
  437.  
  438.         #2055         (Celia's hardsuit is #2055.        )
  439.         location
  440.         #2032         (Celia again                       )
  441.         dbcmp         (Has she got her hardsuit with her?)
  442.         if me @ "Watch out-- she's wearing her hardsuit!" notify then
  443. ;
  444.  
  445.  
  446.     Note that this program uses no variables (except for the universally
  447.     defined ME variable.)
  448.  
  449.  
  450. In Muck, this program would be attached to, say, a homing device or a magic
  451. staff.  Now, if Boomer ever wants to find Celia, he can, and he'll even know
  452. if she's defenseless or she's got her armor.
  453.  
  454. Without the comments and spaced out like you might see normally, this program
  455. looks like:
  456.  
  457. : far_vision
  458.         #2032 dup
  459.         name " is currently in " strcat
  460.         swap location name
  461.         "." strcat strcat                   (Now we know where she is.)
  462.  
  463.         me @ swap notify
  464.  
  465.         #2055 location
  466.         #2032 dbcmp
  467.         if me @ "Watch out-- she's wearing her hardsuit!" notify
  468.         then
  469. ;
  470.  
  471.  
  472. Words can also be called by other words; to do this, you treat your other
  473. words just like library functions when you use them.  When you have more
  474. than one word in the same program, the word which is listed *last* is
  475. the one executed, and all the ones listed before it are subroutines.  The
  476. above program could be rewritten:
  477.  
  478. : celia-identity
  479.         #2032
  480. ;
  481.  
  482. : far_vision
  483.         celia-identity dup
  484.         name " is currently in " strcat
  485.         swap location name
  486.         "." strcat strcat                   (Now we know where she is.)
  487.  
  488.         me @ swap notify
  489.  
  490.         #2055
  491.         location celia-identity dbcmp (Using celia-identity and spacing the )
  492.                                       (commands like this makes this bit a  )
  493.                                       (little easier to understand.         )
  494.  
  495.         if me @ "Watch out-- she's wearing her hardsuit!" notify
  496.         then
  497. ;
  498.  
  499.  
  500. Oodles and oodles of other neat MUF library routines are available, too
  501. numerous to be detailed in an introduction such as this.  A complete list,
  502. as well as sample code, is available from such spiffy ftp sites as
  503. prince.white.toronto.edu and belch.berkeley.edu.
  504.  
  505. If you're interested in seeing more sample code, write to me for
  506. program listings for the Pan Galactic Gargle Blaster, walkie-talkies,
  507. and several useful library routines.
  508.  
  509. Stinglai "Two Sheds" Ka'abi
  510. Mail to: blojo@ocf.berkeley.edu
  511.  
  512. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  513. "We are too proud to fight."             --Woodrow Wilson 1856-1924
  514. "Violence never settles anything."       --Genghis Khan 1162-1227
  515. "The mice voted to bell the cat."        --Aesop c. 620-c. 560 B.C.
  516. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  517.  
  518. Coming next week:
  519.         "Life, the Universe, and INTERCAL:"
  520.                 A most excellent introduction to that programming language.
  521.  
  522.  
  523.  
  524.